/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.iec.edp.caf.rpc.api.channel;


import io.iec.edp.caf.rpc.api.entity.ServiceUnitDefinition;
import io.iec.edp.caf.rpc.api.spi.ServiceCenterProvider;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.LinkedHashMap;

/**
 * RpcChanel is a interface which define
 * any communication Chanel,for example:gRPCChanel,HttpChanel......
 * this interface contain serviceRegister、serviceDiscovery、invoke method
 */
public interface RpcChannel {


    /**
     * service register
     * 当前RPC服务的服务粒度是MSU（一种RPC明细服务的聚合），所以注册机制在RPC内部是没有的，由MSU服务接管
     */
    default void serviceRegister(){}

    /**
     * service discover
     * 服务发现，由具体的服务注册中心提供服务
     * @param serviceUnit su Code
     * @return address
     */
    default String serviceDiscover(String serviceUnit){
        ServiceUnitDefinition definition = ServiceUnitDefinition.builder()
                .msu(serviceUnit)
                .build();
        return ServiceCenterProvider.getServiceCenterProvider().discover(definition);
    }

    /**
     * ordinary way to call remote service
     * @param version service version
     * @param serviceId service Id
     * @param parameters remote service parameters
     * @param context client to server context
     * @return
     * @throws IllegalAccessException
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws IOException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     */
     String invokeRemoteService(String serviceId, String version, LinkedHashMap<String, String> parameters,
                                HashMap<String, String> context) throws IllegalAccessException, ClassNotFoundException, InstantiationException, IOException, NoSuchMethodException, InvocationTargetException;

    /**
     * sync remote service to download stream
     * if the file content is so big will OOM,this can use invokeRemoteServiceStreamAsyn
     * @param serviceId service Id
     * @param version service version
     * @param parameters service parameters
     * @param context client to server context
     * @return
     * @throws IllegalAccessException
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws IOException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     */
    InputStream invokeRemoteServiceStream(String serviceId, String version, LinkedHashMap<String, String> parameters,
                                           HashMap<String, String> context) throws IllegalAccessException, ClassNotFoundException, InstantiationException, IOException, NoSuchMethodException, InvocationTargetException;

    /**
     * asyn remote service to download stream
     * @param serviceId service Id
     * @param version service version
     * @param parameters service parameters
     * @param context client to server context
     * @param callback callback function
     * @throws IllegalAccessException
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws IOException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     */
    void invokeRemoteServiceStreamAsyn(String serviceId, String version, LinkedHashMap<String, String> parameters,
                                           HashMap<String, String> context,RpcChanelAsynCallBack callback) throws IllegalAccessException, ClassNotFoundException, InstantiationException, IOException, NoSuchMethodException, InvocationTargetException;

    /**
     * remote service to upload stream
     * @param inputStream file stream
     * @param serviceId service Id
     * @param version service version
     * @param parameters service parameters
     * @param context client to server context
     * @return
     * @throws IllegalAccessException
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws IOException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     */
    String invokeRemoteServiceStream(InputStream inputStream,String serviceId,String version,LinkedHashMap<String, String> parameters,
                                    HashMap<String, String> context) throws IllegalAccessException, ClassNotFoundException, InstantiationException, IOException, NoSuchMethodException, InvocationTargetException;

}
